/*
 * test-sem.c
 *
 * Simple test of semaphores. Checks that they do, in fact, provide:
 * 1)mutual exclusion. ( 1 unit semaphore) 
 * 2)wait and post ( >1 unit semaphore)
 * 
 */
 
/* http://www.cplusplus.com/reference/clibrary/*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> 
#include <sthread.h>

static int counter = 0;
static int ran_thread = 0;
static sthread_sem_t sem;

void *thread_start(void *);

int main(int argc, char **argv)
{
	int checks;
	sthread_t thread;
	printf("Testing sthread_sem_*, impl: %s\n",
		   (sthread_get_impl() == STHREAD_PTHREAD_IMPL) ? "pthread" : "user");
	
	sthread_init();
	
	//TESTE 1
	printf("Testing semaphore initialized with 1 unit:...");
	sem = sthread_sem_init(1);
	sthread_sem_wait(sem);
	
	if ( (thread=sthread_create(thread_start, (void*)1, 1, 1, 0)) == NULL) {
		printf("\nsthread_create failed\n");
		exit(1);
	}
	
	/* Wait until the other thread has at least started,
	 * to give it a chance at getting through the mutex incorrectly. */
	while (ran_thread == 0) {
		sthread_yield();
	}
	
	/* The other thread has run, but shouldn't have been
	 * able to affect counter (note that this is not a great test
	 * for preemptive scheduler, since the other thread's sequence
	 * is not atomic). */   
	assert(counter == 0);
	
	/* This should let the other thread run at some point. */
	sthread_sem_post(sem);
	
	/* Allow up to 100 checks in case the scheduler doesn't
	 * decide to run the other thread for a really long time. */
	checks = 100;
	while (checks > 0) {
		sthread_sem_wait(sem);
		if (counter != 0) {
			/* The other thread ran, got the lock,
			 * and incrmented the counter: test passes. */
			checks = -1;
		} else {
			checks--;
		}
		sthread_sem_post(sem);
		
		/* Nudge the scheduler to run the other thread: */
		sthread_yield();
	}
	
	if (checks == -1) {	
		printf("passed\n");
	} else {
		printf("failed\n");
	}
	counter = 0;
	void* ret;
	sthread_join(thread,&ret);
	sthread_sem_destroy(sem);
	

	printf("Testing semaphore initialized with %d unit:...",3);
	counter=0;	
	sem = sthread_sem_init(3);
	int i;
	
	for( i=0; i < 4; i++){	
		if ( (thread=sthread_create(thread_start, (void*)1, 1, 1, 0)) == NULL) {
		printf("\nsthread_create failed\n");
		exit(1);
		}
	}
	/* Allow up to 100 checks in case the scheduler doesn't
	 * decide to run the other thread for a really long time. */
	checks = 100;
	while (checks > 0) {
		if (counter > 3) {// foi inicializado com 3 logo apenas 3 threads incrementam o counter
			checks = -1;
		} else {
			checks--;
		}		
		sthread_yield();
	}	
	if (checks == -1) {	
		printf("passed\n");
	} else {
		printf("failed\n");
	}
	
	//testar a ordem de insersao na fila
	
	
	
	
	
	return 0;
}


/* Try and get the lock.
 * When acquired, mark a global to let main know. */
void *thread_start(void *arg)
{
	/* indicate we got in to this thread */
	ran_thread = 1;
	/* should wait until main() has released us */
	sthread_sem_wait(sem);
	++counter;
	sthread_sem_post(sem);
	sthread_exit(NULL);
	return 0;
}

/* Try and get the lock.
 * When acquired, mark a global to let main know. */
